package org.swidgets.sgrid;

import java.util.ArrayList;
import java.util.List;

import org.swidgets.base.IsPaginable;
import org.swidgets.base.Result;
import org.swidgets.base.SColumn;
import org.swidgets.base.SDataModel;
import org.swidgets.base.spaginator.SPaginator;

import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.SourcesTableEvents;
import com.google.gwt.user.client.ui.TableListener;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.HTMLTable.ColumnFormatter;
import com.google.gwt.user.client.ui.HTMLTable.RowFormatter;


public class SGrid extends Composite implements IsPaginable,TableListener {
	private SDataModel gridModel;
	private AsyncDataReader dataSource;
	private VerticalPanel container=new VerticalPanel();
	private HorizontalPanel caption=new HorizontalPanel();
	private ScrollPanel fullBody=new ScrollPanel();
	//private VerticalPanel body=new VerticalPanel();
	private Grid grid=new Grid();
	private int lastrowSelect=-1;
	
	
	private List rowClickListeners=new ArrayList();
	
	private boolean[] selectedRows;
	
	private SPaginator paginator;
	
	private final static AsyncDataReader designTimeReader = new AsyncDataReader() {
		public void loadTableData(int start, int limit,
				AsyncCallback callback) {
			String[][] stringServerData = new String[10][3];
			for(int i=0;i<stringServerData.length;i++){
				stringServerData[i][0] = "Column 1, "+i;
				stringServerData[i][1] = "Column 2, "+i;
				stringServerData[i][2] = "Column 3, "+i;
			}
			
			Result result = new Result();
			result.setData(stringServerData);
			result.setTotalRecords(stringServerData.length);
						
			callback.onSuccess(result);
		}
	};
	
	private final static SDataModel designTimeModel = new SimpleStringArrayTableModel() {
		public String[] getColumnName() {
			return new String[]{"Column 1", "Column 2", "Column 3"};
		}
		public String[] getColumnWidth(){
			return new String[]{"120px","120px","120px"};
		}		
	};
	
		
	private void initSGrid(){
		initWidget(container);
		container.add(caption);
		container.add(fullBody);
		container.add(paginator);
		this.fullBody.add(grid);
		grid.addTableListener(this);
		grid.setStyleName("SRowCell");
		fullBody.setAlwaysShowScrollBars(false);
		fullBody.setHeight("100%");
		caption.setStyleName("SGridHeader");
		container.setWidth("100%");		
	}
	public SGrid(){
		this.paginator=new SPaginator();
		this.gridModel=designTimeModel;
		this.dataSource=designTimeReader;
		initSGrid();
		this.createHeader();
		container.setWidth("360px");
	}
	
	public SGrid(final SDataModel gridModel,final AsyncDataReader dataSource){
		super();

		if (isDesignTime()) {
			this.paginator=new SPaginator(null);
			this.gridModel=gridModel!=null?gridModel:designTimeModel;
			this.dataSource=dataSource!=null?dataSource:designTimeReader;
			
		}
		else {
			this.paginator=new SPaginator(this);
			this.gridModel=gridModel;
			this.dataSource=dataSource;			
		}
		
		initSGrid();
		this.createHeader();
		container.setWidth("100%");
	}
	
	private static final boolean isDesignTime() {
		return false;
	}

	public void createHeader(){
		SColumn col;
		int rc=gridModel.getMetaData().length;
		for(int i=0;i<rc;i++){
			col=gridModel.getMetaData()[i];
			caption.add(col.getCaption());
			caption.getWidget(i).setWidth(col.getWidth());
		}
	}
	
	protected void onLoad() {
		load();
	}

	public void setBodyHeight(String height){
		fullBody.setHeight(height);
	}
	

		
	private void loadData(){
		int cols=this.gridModel.getMetaData().length;
		int rows=gridModel.getCurrentRecords();
		String[] dati;
		grid.resize(rows,cols);
		
			
		ColumnFormatter cf=grid.getColumnFormatter();
		for(int i=0;i<cols;i++){
			cf.setWidth(i,this.gridModel.getMetaData()[i].getWidth());
		}
		selectedRows=new boolean[rows];
		
		RowFormatter rf=grid.getRowFormatter();
		for(int r=0;r<rows;r++){
			selectedRows[r]=false;
			dati=(String[])gridModel.getRowData(r);
			if(r%2==0){
				rf.setStyleName(r,"SRowEven");
			}else{
				rf.setStyleName(r,"SRowOdd");
			}
			for(int c=0;c<cols;c++){
				HTML w=new HTML(dati[c]);
				grid.setWidget(r, c, w);
			}
		}
		
	}
	
	
	public void load() {
		lastrowSelect=-1;
		if(dataSource==null)
			return;
		this.dataSource.loadTableData(this.paginator.getFirstRecord(), this.paginator.getRecordsPerPage(), new AsyncCallback(){
			public void onFailure(Throwable caught) {
				Window.alert(caught.getMessage());
			}

			public void onSuccess(Object result) {
				gridModel.setData((Result)result);
				paginator.refresh(gridModel.getCurrentRecords(),gridModel.getTotalRecords());
				if(result==null)
					return;
				loadData();
			}
			
		});
		
	}

	public int getRowCount(){
		//return this.body.getWidgetCount();
		return grid.getRowCount();
	}

	
	
	/**
	*@gwt.typeArgs <Object>
	*/
	public List getSelectedRows(){
		List ret=new ArrayList();
		for(int i=0;i<selectedRows.length;i++)
			if(selectedRows[i])
				ret.add(gridModel.getRowData(i));
		return ret;
	}
	public void paginatorReload() {
		load();
	}
	
	
	public void onCellClicked(SourcesTableEvents sender, int row, int cell) {
		if(selectedRows[row]){
			selectedRows[row]=false;
			if(row%2==0)
				grid.getRowFormatter().setStyleName(row, "SRowEven");
			else
				grid.getRowFormatter().setStyleName(row, "SRowOdd");
		}
		else{
			lastrowSelect=row;
			selectedRows[row]=true;
			grid.getRowFormatter().setStyleName(row, "SRowSelected");
		}
	}
	
	public void addTableListener(TableListener listener) {
		grid.addTableListener(listener);
	}
	
	public class RowClicked{
		public boolean isSelected=false;
		public Object []data;
		public RowClicked() {}
		
	}
	
	public RowClicked getRowClicked(){
		RowClicked ret=new RowClicked();
		if(lastrowSelect>=0){
			ret.isSelected=selectedRows[lastrowSelect];
			ret.data=(Object[])gridModel.getRowData(this.lastrowSelect);
			return ret;
		}
		else
			return null;		
	}
	
	
}

